home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CICA Windows Explosion!
/
The CICA Windows Explosion! - Disc 2.iso
/
programr
/
upc12bs1.zip
/
UUCICO
/
ulibip.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-10-02
|
27KB
|
814 lines
/*--------------------------------------------------------------------*/
/* u l i b i p . c */
/* */
/* TCP/IP port communications driver for Windows sockets */
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
/* Copyright (c) David M. Watt 1993, All Rights Reserved */
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
/* Changes Copyright (c) 1989-1993 by Kendra Electronic */
/* Wonderworks. */
/* */
/* All rights reserved except those explicitly granted by the */
/* UUPC/extended license agreement. */
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
/* RCS Information */
/*--------------------------------------------------------------------*/
/*
* $Id: ulibip.c 1.6 1993/10/02 23:12:35 dmwatt Exp $
*
* $Log: ulibip.c $
* Revision 1.6 1993/10/02 23:12:35 dmwatt
* Winsock error message support
*
* Revision 1.5 1993/09/26 03:32:27 dmwatt
* Use Standard Windows NT error message module
*
* Revision 1.4 1993/09/25 03:07:56 ahd
* Addition error traps by Dave Watt
*
* Revision 1.3 1993/09/23 03:26:51 ahd
* Correct setting of carrier detect
*
* Revision 1.2 1993/09/21 01:42:13 ahd
* Use standard MAXPACK limit for save buffer size
*
* Revision 1.1 1993/09/20 04:48:25 ahd
* Initial revision
*
*/
/*--------------------------------------------------------------------*/
/* System include files */
/*--------------------------------------------------------------------*/
#include <windows.h>
#include "winsock.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
/*--------------------------------------------------------------------*/
/* UUPC/extended include files */
/*--------------------------------------------------------------------*/
#include "lib.h"
#include "hlib.h"
#include "ulib.h"
#include "comm.h" // Modem status bits
#include "ssleep.h"
#include "catcher.h"
#include "commlib.h" // Trace functions, etc.
#include "pwserr.h" // Windows sockets error messages
#ifdef _Windows
#include "pwinsock.h" // definitions for 16 bit Winsock functions
#endif
/*--------------------------------------------------------------------*/
/* Internal prototypes */
/*--------------------------------------------------------------------*/
void AtWinsockExit(void);
boolean IsFatalSocketError(int err);
void tcloseline(void);
/*--------------------------------------------------------------------*/
/* Global variables */
/*--------------------------------------------------------------------*/
static boolean carrierDetect = FALSE;
currentfile();
static boolean hangupNeeded = TRUE;
extern boolean winsockActive; // Initialized in catcher.c
static SOCKET pollingSock = INVALID_SOCKET; // The current polling socket
static SOCKET connectedSock = INVALID_SOCKET; // The currently connected socket
static boolean connectionDied = FALSE; // The current connection failed
/*--------------------------------------------------------------------*/
/* Local defines */
/*--------------------------------------------------------------------*/
#ifndef MAKEWORD
#define MAKEWORD(a, b) ((WORD)(((BYTE)(a)) | ((WORD)((BYTE)(b))) << 8))
#endif
/*--------------------------------------------------------------------*/
/* I n i t W i n s o c k */
/* */
/* Start the Windows sockets DLL */
/*--------------------------------------------------------------------*/
boolean InitWinsock(void)
{
WSADATA WSAData;
int status;
static boolean firstPass = TRUE;
if ( winsockActive )
return TRUE;
/*--------------------------------------------------------------------*/
/* The atexit() must precede the WSAStartup() so the */
/* FreeLibrary() call gets done */
/*--------------------------------------------------------------------*/
if ( firstPass )
{
firstPass = FALSE;
atexit(AtWinsockExit);
}
#ifdef _Windows
if (!pWinSockInit())
return FALSE;
#endif
// status = WSAStartup(MAKEWORD(1,1), &WSAData);
status = WSAStartup(0x0101, &WSAData);
if (status != 0)
{
printf("WSAStartup Error: %d", status);
return FALSE;
}
winsockActive = TRUE;
return TRUE;
} /* InitWinsock */
/*--------------------------------------------------------------------*/
/* A t W i n s o c k E x i t */
/* */
/* Clean up Windows DLL at shutdown */
/*--------------------------------------------------------------------*/
void AtWinsockExit(void)
{
WSACleanup();
#ifdef _Windows
pWinSockExit();
#endif
winsockActive = FALSE;
} /* AtWinsockExit */
/*--------------------------------------------------------------------*/
/* t o p e n a c t i v e */
/* */
/* Open an active socket connection for I/O */
/*--------------------------------------------------------------------*/
#ifdef __TURBOC__
#pragma argsused
#endif
int tactiveopenline(char *name, BPS bps, const boolean direct)
{
SOCKADDR_IN sin;
LPHOSTENT phe;
LPSERVENT pse;
if (!InitWinsock()) // Initialize library?
return TRUE; // No --> Report error
if (portActive) /* Was the port already active? */
closeline(); /* Yes --> Shutdown it before open */
printmsg(15, "tactiveopenline: %s", name);
norecovery = FALSE; // Flag we need a graceful shutdown after
// Ctrl-BREAK
carrierDetect = FALSE; /* No modem connected yet */
connectionDied = FALSE; /* The connection hasn't failed yet */
/*--------------------------------------------------------------------*/
/* Get remote host name */
/*--------------------------------------------------------------------*/
sin.sin_family = AF_INET;
phe = gethostbyname(name);
if (phe)
#ifdef _Windows
_fmemcpy((char FAR *) &(sin.sin_addr),
(char FAR *) phe->h_addr,
phe->h_length);
#else
memcpy((char FAR *) &(sin.sin_addr),
(char FAR *) phe->h_addr,
phe->h_length);
#endif
else {
sin.sin_addr.s_addr = inet_addr(name);
if ( sin.sin_addr.s_addr == INADDR_NONE )
{
int wsErr = WSAGetLastError();
printmsg(0, "tactiveopenline: "
"Is '%s' listed in the hosts file or a valid IP address?",
name);
printWSerror("gethostbyname", wsErr);
return TRUE;
}
} /* else */
/*--------------------------------------------------------------------*/
/* Get the TCP/IP port number */
/*--------------------------------------------------------------------*/
pse = getservbyname("uucp", "tcp");
if (pse == NULL)
{
int wsErr = WSAGetLastError();
sin.sin_port = 540;
printWSerror("getservbyname", wsErr);
printmsg(0, "tactiveopenline: using port %d", (int)sin.sin_port);
}
else
sin.sin_port = pse->s_port;
connectedSock = socket( AF_INET, SOCK_STREAM, 0);
if (connectedSock == INVALID_SOCKET)
{
printmsg(0, "tactiveopenline: socket() failed");
return TRUE;
}
if (connect( connectedSock, (PSOCKADDR) &sin, sizeof(sin)) < 0)
{
int wsErr = WSAGetLastError();
printmsg(0, "tactiveopenline: connect() failed");
printWSerror("connect", wsErr);
closesocket( connectedSock );
connectedSock = INVALID_SOCKET;
return TRUE;
}
traceStart( name );
portActive = TRUE; /* record status for error handler */
carrierDetect = TRUE; // Carrier detect = connection
return FALSE; // Return success to caller
} /* tactiveopenline */
/*--------------------------------------------------------------------*/
/* t o p e n p a s s i v e */
/* */
/* Listen on a socket for an incoming uucp connection */
/*--------------------------------------------------------------------*/
#ifdef __TURBOC__
#pragma argsused
#endif
int tpassiveopenline(char *name, BPS bps, const boolean direct)
{
SOCKADDR_IN sin;
LPSERVENT pse;
if (!InitWinsock()) // Initialize library?
return TRUE; // No --> Report error
if (portActive) /* Was the port already active? */
closeline(); /* Yes --> Shutdown it before open */
printmsg(15, "tpassiveopenline: opening passive connection");
norecovery = FALSE; // Flag we need a graceful shutdown after
// Ctrl-BREAK
carrierDetect = FALSE; /* No network connection yet */
connectionDied = FALSE; /* The connection hasn't failed yet */
/*--------------------------------------------------------------------*/
/* Fill in host and family info */
/*--------------------------------------------------------------------*/
sin.sin_family = AF_INET;
/*--------------------------------------------------------------------*/
/* Fill in service information for tcp */
/*--------------------------------------------------------------------*/
printmsg(15, "tpassiveopenline: doing getservbyname");
pse = getservbyname("uucp", "tcp");
if (pse == NULL)
{
int wsErr = WSAGetLastError();
sin.sin_port = 540;
printWSerror("getservbyname", wsErr);
printmsg(0, "tpassiveopenline: using port %d",
(int) sin.sin_port);
}
else
sin.sin_port = pse->s_port;
sin.sin_addr.s_addr = 0;
printmsg(5, "tpassiveopenline: waiting on port %d",
(int)ntohs(sin.sin_port));
/*--------------------------------------------------------------------*/
/* Create and bind TCP socket */
/*--------------------------------------------------------------------*/
printmsg(15, "tpassiveopen: doing socket()");
pollingSock = socket( AF_INET, SOCK_STREAM, 0);
if (pollingSock == INVALID_SOCKET)
{
int wsErr = WSAGetLastError();
printmsg(0, "tpassiveopen: socket() failed");
printWSerror("socket", wsErr);
return TRUE;
}
printmsg(15, "tpassiveopen: doing bind()");
if (bind(pollingSock,
(struct sockaddr FAR *) &sin,
sizeof(sin)) == SOCKET_ERROR)
{
int wsErr = WSAGetLastError();
printmsg(0, "tpassiveopen: bind(pollingSock) failed");
printWSerror("bind", wsErr);
return TRUE; // report failure
}
printmsg(15, "tpassiveopen: doing listen()");
if (listen(pollingSock, 2) == SOCKET_ERROR)
{
int wsErr = WSAGetLastError();
printmsg(0, "tpassiveopen: listen(pollingSock) failed");
printWSerror("listen", wsErr);
return TRUE;
}
traceStart( name );
portActive = TRUE; /* record status for error handler */
return FALSE; // Return success to caller
} /* tpassiveopen */
/*--------------------------------------------------------------------*/
/* t s r e a d */
/* */
/* Read from the network socket */
/* */
/* Non-blocking read essential to "g" protocol. See */
/* "dcpgpkt.c" for description. This all changes in a */
/* multi-tasking system. Requests for I/O should get queued */
/* and an event flag given. Then the requesting process (e.g. */
/* gmachine()) waits for the event flag to fire processing */
/* either a read or a write. Could be implemented on VAX/VMS */
/* or DG but not MS-DOS. */
/*--------------------------------------------------------------------*/
unsigned int tsread(char *output, unsigned int wanted, unsigned int timeout)
{
fd_set readfds;
struct timeval tm;
int nReady;
static char save[MAXPACK];
static unsigned short bufsize = 0;
time_t stop_time ;
time_t now ;
/*--------------------------------------------------------------------*/
/* Determine if our internal buffer has the data */
/*--------------------------------------------------------------------*/
if (bufsize >= wanted)
{
memmove( output, save, wanted );
bufsize -= wanted;
if ( bufsize ) /* Any data left over? */
memmove( save, &save[wanted], bufsize ); /* Yes --> Save it*/
return wanted + bufsize;
} /* if */
if (connectionDied || connectedSock == INVALID_SOCKET)
{ // Haven't accepted a connection yet?
return 0;
}
/*--------------------------------------------------------------------*/
/* Determine when to stop processing */
/*--------------------------------------------------------------------*/
if ( timeout == 0 )
{
stop_time = 0;
now = 1; /* Any number greater than stop time */
}
else {
time( & now );
stop_time = now + timeout;
}
do {
int received;
int needed = wanted - bufsize;
/*--------------------------------------------------------------------*/
/* Initialize fd_set structure for select() call */
/*--------------------------------------------------------------------*/
FD_ZERO(&readfds);
FD_SET(connectedSock, &readfds);
/*--------------------------------------------------------------------*/
/* Handle an aborted program */
/*--------------------------------------------------------------------*/
if ( terminate_processing )
{
static boolean recurse = FALSE;
if ( ! recurse )
{
printmsg(2,"sread: User aborted processing");
recurse = TRUE;
}
return 0;
}
/*--------------------------------------------------------------------*/
/* Special case for network sockets: block for at least 5 */
/* msec if we have to read at least one character (this */
/* needs to be tuned) */
/*--------------------------------------------------------------------*/
if (stop_time > now )
{
tm.tv_sec = stop_time - now;
tm.tv_usec = 0;
}
else {
tm.tv_usec = 5000;
tm.tv_sec = 0;
}
/*--------------------------------------------------------------------*/
/* Read the data from the socket */
/*--------------------------------------------------------------------*/
nReady = select(1, &readfds, NULL, NULL, &tm);
if (nReady == SOCKET_ERROR)
{
int err = WSAGetLastError();
printmsg(0, "tsread: error in select()");
printWSerror("select", err);
if (IsFatalSocketError(err))
{
shutdown(connectedSock, 2); // Fail both reads and writes
connectionDied = TRUE;
}
bufsize = 0;
return 0;
}
else if (nReady == 0)
{
printmsg(5, "tsread: timeout after %d seconds",timeout);
bufsize = 0;
return 0;
}
else {
received = recv(connectedSock, &save[bufsize], needed, 0);
if (received == SOCKET_ERROR)
{
int wsErr = WSAGetLastError();
printmsg(0, "tsread: recv() failed");
printWSerror("recv", wsErr);
bufsize = 0;
return 0;
}
} /* else */
#ifdef UDEBUG
printmsg(15,"sread: Want %d characters, received %d, total %d in buffer",
(int) wanted, (int) received, (int) bufsize + received);
#endif
/*--------------------------------------------------------------------*/
/* Log the newly received data */
/*--------------------------------------------------------------------*/
traceData( &save[bufsize], received, FALSE );
/*--------------------------------------------------------------------*/
/* If we got the data, return it to the caller */
/*--------------------------------------------------------------------*/
bufsize += received;
if ( bufsize == wanted )
{
memmove( output, save, bufsize);
bufsize = 0;
if (debuglevel > 14)
fwrite(output,1,bufsize,stdout);
return wanted;
} /* if */
/*--------------------------------------------------------------------*/
/* Update the clock for the next pass */
/*--------------------------------------------------------------------*/
if (stop_time > 0)
time( &now );
} while (stop_time > now);
/*--------------------------------------------------------------------*/
/* We don't have enough data; report what we do have */
/*--------------------------------------------------------------------*/
return bufsize;
} /* tsread */
/*--------------------------------------------------------------------*/
/* t s w r i t e */
/* */
/* Write to the open socket */
/* Note: this is non-blocking, so we've got to use select() to */
/* gradually write out the entire buffer */
/*--------------------------------------------------------------------*/
int tswrite(char *data, unsigned int len)
{
int status;
/* Has connection died? */
if (connectionDied || connectedSock == INVALID_SOCKET)
return 0;
status = send(connectedSock, data, len, 0);
if (status == SOCKET_ERROR)
{
int err;
err = WSAGetLastError();
printmsg(0, "tswrite: Error sending data to socket");
printWSerror("send", err);
if (IsFatalSocketError(err))
{
shutdown(connectedSock, 2); // Fail both reads and writes
connectionDied = TRUE;
}
return 0;
}
if (status < len)
{
printmsg(0,"tswrite: Write to network failed.");
return status;
}
/*--------------------------------------------------------------------*/
/* Log the data written */
/*--------------------------------------------------------------------*/
traceData( data, len, TRUE );
/*--------------------------------------------------------------------*/
/* Return byte count transmitted to caller */
/*--------------------------------------------------------------------*/
return len;
} /* tswrite */
/*--------------------------------------------------------------------*/
/* t s s e n d b r k */
/* */
/* Send a break signal over the network */
/*--------------------------------------------------------------------*/
#ifdef __TURBOC__
#pragma argsused
#endif
void tssendbrk(unsigned int duration)
{
printmsg(12, "tsendbrk: ignored break of duration %d", duration);
return;
} /* tssendbrk */
/*--------------------------------------------------------------------*/
/* t c l o s e l i n e */
/* */
/* Close the serial port down */
/*--------------------------------------------------------------------*/
void tcloseline(void)
{
if (!portActive)
panic();
portActive = FALSE; /* flag port closed for error handler */
if (connectedSock != INVALID_SOCKET)
{
closesocket(connectedSock);
connectedSock = INVALID_SOCKET;
}
if (pollingSock != INVALID_SOCKET)
{
closesocket(pollingSock);
pollingSock = INVALID_SOCKET;
}
carrierDetect = FALSE; /* No network connection yet */
traceStop();
} /* tcloseline */
/*--------------------------------------------------------------------*/
/* t h a n g u p */
/* */
/* Break the connection with the remote system. */
/*--------------------------------------------------------------------*/
void thangup( void )
{
if (!hangupNeeded)
return;
hangupNeeded = FALSE;
if (connectedSock != INVALID_SOCKET)
{
closesocket(connectedSock);
connectedSock = INVALID_SOCKET;
}
if (pollingSock != INVALID_SOCKET)
{
closesocket(pollingSock);
pollingSock = INVALID_SOCKET;
}
carrierDetect = FALSE; /* No network connection yet */
} /* thangup */
/*--------------------------------------------------------------------*/
/* t S I O S p e e d */
/* */
/* Re-specify the speed of an opened serial port */
/*--------------------------------------------------------------------*/
#ifdef __TURBOC__
#pragma argsused
#endif
void tSIOSpeed(BPS bps)
{
return; /* Irrelevant on network */
} /* iSIOSpeed */
/*--------------------------------------------------------------------*/
/* t f l o w c o n t r o l */
/* */
/* Enable/Disable in band (XON/XOFF) flow control */
/*--------------------------------------------------------------------*/
#ifdef __TURBOC__
#pragma argsused
#endif
void tflowcontrol( boolean flow )
{
return; /* Irrelevant on network (we hope) */
} /* tflowcontrol */
/*--------------------------------------------------------------------*/
/* t G e t S p e e d */
/* */
/* Report current speed of communications connection */
/*--------------------------------------------------------------------*/
BPS tGetSpeed( void )
{
return 57600; // Arbitary large number to avoid possible
// divide by zero error in caller
} /* GetSpeed */
/*--------------------------------------------------------------------*/
/* t C D */
/* */
/* Report if we have carrier detect and lost it */
/*--------------------------------------------------------------------*/
boolean tCD( void )
{
boolean online = carrierDetect;
return online;
} /* tCD */
/*--------------------------------------------------------------------*/
/* t W a i t F o r N e t C o n n e c t */
/* */
/* Wait for remote system to connect to our waiting server */
/*--------------------------------------------------------------------*/
boolean tWaitForNetConnect(int timeout)
{
fd_set readfds;
int nReady;
struct timeval tm;
tm.tv_sec = timeout;
tm.tv_usec = 0;
FD_ZERO(&readfds);
FD_SET(pollingSock, &readfds);
nReady = select(1, &readfds, NULL, NULL, &tm);
if (nReady == SOCKET_ERROR)
{
int wsErr = WSAGetLastError();
printmsg(0, "WaitForNetConnect: select() failed");
printWSerror("select", wsErr);
return FALSE;
}
else if (nReady == 0)
{
printmsg(5, "WaitForNetConnect: select() timed out");
return FALSE;
}
connectedSock = accept(pollingSock, NULL, NULL);
if (connectedSock == INVALID_SOCKET)
{
int wsErr = WSAGetLastError();
printmsg(0, "WaitForNetConnect: could not accept a connection");
printWSerror("accept", wsErr);
}
carrierDetect = TRUE;
return TRUE;
} /* tWaitForNetConnect */
boolean IsFatalSocketError(int err)
{
if (err == WSAENOTSOCK ||
err == WSAENETDOWN ||
err == WSAENETRESET ||
err == WSAECONNABORTED ||
err == WSAECONNRESET ||
err == WSAENOTCONN ||
err == WSAECONNREFUSED ||
err == WSAEHOSTDOWN ||
err == WSAEHOSTUNREACH)
return TRUE;
else
return FALSE;
}